package cn.hdu.liang.ch02.classpath;

import java.io.File;
import java.io.IOException;

public class ClassPath {
    //jre路径
    private String jreDir;

    //分别存放三种路径
    private Entry bootClasspath;
    private Entry extClasspath;
    private Entry userClasspath;

    /**
     * 根据路径初始化
     *
     * @param jreOption -Xjre选项指定的 启动类路径和扩展类路径
     * @param cpOption  -cp选项指定的 用户类路径
     */
    public ClassPath(String jreOption, String cpOption) {
        jreDir = getJreDir(jreOption);
        bootClasspath = parseBootClasspath();
        extClasspath = parseExtClasspath();
        userClasspath = parseUserClasspath(cpOption);
    }


    //这里参数传进来的是: /usr/lib/jvm/default-java/jre
    private Entry parseBootClasspath() {
        // jre/lib/* 启动类路径
        String jreLibPath = jreDir + File.separator + "lib" + File.separator + "*";
        return new WildcardEntry(jreLibPath);
    }

    private Entry parseExtClasspath() {
        // jre/lib/ext/* 扩展类路径
        String jreExtPath = jreDir + File.separator + "lib" + File.separator + "ext" + File.separator + "*";
        return new WildcardEntry(jreExtPath);
    }

    private Entry parseUserClasspath(String cpOption) {
        // 用户自定义路径
        return Entry.createEntry(cpOption);
    }

    //确定传进来的jre的路径是否有效
    private String getJreDir(String jreOption) {
        File jreFile;
        if(jreOption != null && !jreOption.equals("")) {
            jreFile = new File(jreOption);
            if(jreFile.exists()) {
                return jreOption;
            }
        }

        //jreOption选项为空，那么在当前路径找
        jreFile = new File("jre");
        if(jreFile.exists()) {
            return jreFile.getAbsolutePath();
        }

        //在JAVA_HOME中找
        String javaHome = System.getenv("JAVA_HOME");
        if(javaHome != null) {
            return javaHome + File.separator + "jre";
        }

        throw new RuntimeException("无法找到 jre 指定文件夹! ");
    }

    /**
     * ClassPath 对外的统一接口,实例化ClassPath时传入 userPath 路径和类名就可以读取字节码文件
     * 读取className 对应的字节码,注意顺序,我们的查找次序是:
     * bootClasspath => extClasspath => userClasspath;
     */
    public byte[] readClass(String className) {
        //注意，用命令行加载java文件时，只写文件名，所有这里统一为文件名后补上“.class”的后缀；
        className = className + ".class";
        byte[] data;
        try {
            data = bootClasspath.readClass(className);
            if(data != null) {
                return data;
            }

            data = extClasspath.readClass(className);
            if(data != null) {
                return data;
            }

            data = userClasspath.readClass(className);
            if(data != null) {
                return data;
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("找不到类" + className);
    }

    @Override
    public String toString() {
        return userClasspath.className();
    }
}
